package com.huizhan.web.controller;

import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.stereotype.Controller;
import org.springframework.ui.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.domain.Sort.*;
import io.swagger.annotations.*;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.*;
import me.chanjar.weixin.mp.api.impl.*;
import me.chanjar.weixin.mp.bean.result.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.net.*;

import com.google.zxing.*;
import com.google.zxing.client.j2se.*;
import com.google.zxing.common.*;
import com.google.zxing.qrcode.*;
import com.huizhan.web.dao.*;
import com.huizhan.web.model.*;

/**
 * 微信
 */
@Controller
@Api(tags = "Wechat", description = "微信")
public class WechatController {

    @Value("${appid}")
    private String appId;
    @Value("${appsecret}")
    private String appSecret;

    @Autowired
    private ProjectDao dao;

    @Autowired
    private TicketTypeDao tdao;

    @Autowired
    private TicketRecordDao rdao;

    @Autowired
    private TicketDao ticketDao;

    @Autowired
    private OrderFormDao formDao;

    @Autowired
    private TicketComplimentaryDao tcDao;

    @Autowired
    private DistributeDao ddao;

    @Autowired
    private DocumentDao dDao;

    /**
     * 票终端
     * 
     * @return
     */
    @GetMapping("/{type},{code}")
    public ModelAndView tickek(@PathVariable Long type, @PathVariable String code) {
        ModelAndView map = new ModelAndView();
        Optional<TicketType> ticketType = tdao.findById(type);
        if (ticketType.isPresent()) {
            Ticket ticket = null;
            try {
                ticket = ticketDao.findByTicketTypeIdAndCode(type, code);
            } catch (Exception e) {
                List<Ticket> ts = ticketDao.findByWhere(type, code);

                ticket = ts.get(0);
            }

            if (ticket != null) {
                map.addObject("bg", ticketType.get().getUrl());
                map.addObject("isPass", ticket.getIsPassage());
                map.addObject("code", ticket.getCode());
                map.addObject("banner", ticket.getBanner());
                map.addObject("idnumber", ticket.getIdNumber());
                map.addObject("width", ticketType.get().getWidth());
                map.addObject("height", ticketType.get().getHeight());
                map.addObject("size", ticketType.get().getQrcodeSize());
                map.addObject("x", ticketType.get().getQrcodeX());
                map.addObject("y", ticketType.get().getQrcodeY());
                map.addObject("type", type);
                map.addObject("code", code);
                map.setViewName("tickek");
            } else {
                map.setStatus(HttpStatus.NOT_FOUND);
            }
        } else {
            map.setStatus(HttpStatus.NOT_FOUND);
        }
        return map;
    }

    /**
     * 赠票
     * 
     * @return
     */
    @GetMapping("/t/{id}")
    public ModelAndView t(@PathVariable Long id) {
        ModelAndView map = new ModelAndView();

        Optional<TicketComplimentary> model = tcDao.findById(id);

        if (model.isPresent()) {
            Optional<Project> project = dao.findById(model.get().getProjectId());

            if (project.isPresent()) {
                map.addObject("bg", project.get().getBanner());
                map.addObject("phone", model.get().getPhone());
                map.addObject("total", model.get().getTotal());
                map.addObject("userNumber", model.get().getUseNumber());
                map.addObject("id", model.get().getTicketComplimentaryId());
                map.addObject("projectId", model.get().getProjectId());
                map.setViewName("t");
            } else {
                map.setStatus(HttpStatus.NOT_FOUND);
            }
        } else {
            map.setStatus(HttpStatus.NOT_FOUND);
        }

        return map;
    }

    /**
     * 证件分发
     * 
     * @return
     */
    @GetMapping("/d/{id}")
    public ModelAndView d(@PathVariable Long id) {
        ModelAndView map = new ModelAndView();

        Optional<Distribute> model = ddao.findById(id);

        if (model.isPresent()) {
            if (model.get().getTotal() - model.get().getUseNumber() > 0) {
                Optional<Project> project = dao.findById(model.get().getProjectId());

                if (project.isPresent()) {
                    map.addObject("bg", project.get().getBanner());
                    map.addObject("phone", model.get().getPhone());
                    map.addObject("total", model.get().getTotal());
                    map.addObject("userNumber", model.get().getUseNumber());
                    map.addObject("id", model.get().getDistributeId());
                    map.addObject("projectId", model.get().getProjectId());
                    map.setViewName("d");
                } else {
                    map.setStatus(HttpStatus.NOT_FOUND);
                }
            } else {
                map.setViewName("document");
            }
        } else {
            map.setStatus(HttpStatus.NOT_FOUND);
        }

        return map;
    }

    /**
     * 生成二维码方法
     *
     * @param content 要生成的内容
     * @param resp    response对象
     * @throws Exception 抛出异常
     */
    @GetMapping("/qrcode/{content}")
    public void getQrcode(@PathVariable String content, HttpServletResponse resp) throws Exception {
        ServletOutputStream stream = null;
        BitMatrix bm = null;
        Map<EncodeHintType, Object> hints = new HashMap<>();

        try {
            stream = resp.getOutputStream();
            // 编码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 边框距
            hints.put(EncodeHintType.MARGIN, 0);
            QRCodeWriter  qrCodeWriter = new QRCodeWriter();
            bm = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, 200, 200, hints);
            MatrixToImageWriter.writeToStream(bm, "png", stream);
           } catch (WriterException e) {
               e.getStackTrace();
           } finally {
               if (stream != null) {
                   stream.flush();
                   stream.close();
                   hints.clear();
                   bm.clear();
               }
           }
       }

    /**
     * 我的赠票
     * @return
     */
    @GetMapping("/document/{id}")
    public  ModelAndView  document(@PathVariable Long id,HttpServletRequest request) 
    {
        ModelAndView map = new ModelAndView();
        
        Optional<Distribute> model= ddao.findById(id);

         if(model.isPresent()){
            Optional<Project> project = dao.findById(model.get().getProjectId());

            if(project.isPresent()){

                Document document = dDao.findByDocumentTypeIdAndPhone(model.get().getDocumentTypeId(), model.get().getPhone());

                if(document!=null){
                    map.addObject("code", document.getCode());
                    map.addObject("hasCode", true);
                }else{
                    map.addObject("hasCode", false);
                }
                map.addObject("id", id);
                map.addObject("banner", project.get().getBanner());
                map.addObject("name", model.get().getName());
                map.setViewName("document"); 
            }else{
                map.setStatus(HttpStatus.NOT_FOUND);
             }
         }else{
            map.setStatus(HttpStatus.NOT_FOUND);
         }

        return map;
    }

    

    /**
     * 我的赠票
     * @return
     */
    @GetMapping("/my/{id}")
    public  ModelAndView  my(@PathVariable Long id,HttpServletRequest request) 
    {
        ModelAndView map = new ModelAndView();
        
        Optional<TicketComplimentary> model= tcDao.findById(id);

         if(model.isPresent()){
            Optional<Project> project = dao.findById(model.get().getProjectId());

            if(project.isPresent()){

                PageRequest pageable = PageRequest.of(0,5,Direction.ASC,"is_Passage"); 
                Page<Ticket> list = ticketDao.findByWhere(id, pageable);
                TicketType type= tdao.getOne(model.get().getTicketTypeId());
                
                for (Ticket ticket : list) {
                    ticket.setAvatar(type.getBanner());
                }

                map.addObject("list", list);
                map.addObject("banner", project.get().getBanner());
                map.addObject("name", model.get().getName());
                map.setViewName("from"); 
            }else{
                map.setStatus(HttpStatus.NOT_FOUND);
             }
         }else{
            map.setStatus(HttpStatus.NOT_FOUND);
         }

        return map;
    }

    /**
     * 我的票
     * @param id
     * @param request
     * @param model
     * @return
     */
    @GetMapping("wechat/from/{id}")
    public String from(@PathVariable String id,HttpServletRequest request,Model model)
    {
        try {
            if(request.getParameter("openId")==null){
                String url=URLEncoder.encode(request.getScheme() + "://" + request.getServerName() + request.getRequestURI(),"utf-8");
                return "redirect:" + request.getScheme() + "://" + request.getServerName() +"/wechat/welcome?projectId="+id+"&returnUrl="+url;
            }else{
                Optional<Project> p =   dao.findById(id);

                if(p.isPresent()){

                    List<OrderForm> list=formDao.findByOpenId(request.getParameter("openId"));
                    List<Ticket> tList=new ArrayList<Ticket>();
                    
                    model.addAttribute("banner", p.get().getBanner());
                    model.addAttribute("list", tList);
                    model.addAttribute("name", p.get().getName());
                    
                    String phone=request.getParameter("phone");

                    for (OrderForm orderForm : list) {
                        if(phone!=null&&!phone.equals("")){

                        }else{
                            phone=orderForm.getPhone();
                        }

                        TicketType type= tdao.getOne(orderForm.getTicketTypeId());
                        tList.addAll(ticketDao.findByOrderItemId(orderForm.getOrderFormId()));

                        for (Ticket ticket : tList) {
                            ticket.setAvatar(type.getBanner());
                        }
                    }

                    if(phone!=null&&!phone.equals("")){
                        List<TicketComplimentary> tc= tcDao.findByProjectIdAndPhone(id, phone);

                        PageRequest pageable = PageRequest.of(0,5,Direction.ASC,"is_Passage"); 

                        for (TicketComplimentary t :tc){
                            TicketType type= tdao.getOne(t.getTicketTypeId());
                            Page<Ticket> page = ticketDao.findByWhere(t.getTicketComplimentaryId(), pageable);
                            
                            for(Ticket ticket : page.getContent()){
                                ticket.setAvatar(type.getBanner());
                                tList.add(ticket);
                            }
                        }

                      List<Ticket> ts= rdao.findByProjectIdAndPhone(id,phone);
                      tList.addAll(ts);
                    }

                }
            }
        } catch (Exception e) {
            
        }
        return "from";
    }


    /**
     * 购票
     * @param id
     * @param request
     * @param model
     * @return
     */
    @GetMapping("wechat/buy/{id}")
    public String buy(@PathVariable Long id,HttpServletRequest request,Model model)
    {
        try {
            Optional<TicketType> t = tdao.findById(id);

            if(t.isPresent()){
                if(request.getParameter("openId")==null){
                    String url=URLEncoder.encode(request.getScheme() + "://" + request.getServerName() +request.getRequestURI(),"utf-8");
                    return "redirect:" + request.getScheme() + "://" + request.getServerName() +"/wechat/welcome?projectId="+t.get().getProjectId()+"&returnUrl="+url;
                }else{
                    model.addAttribute("openId", request.getParameter("openId"));
                    model.addAttribute("rule", t.get().getRule());
                    model.addAttribute("number", t.get().getNumber());
                    model.addAttribute("person", t.get().getPerson());
                    model.addAttribute("top", t.get().getTop());
                    model.addAttribute("price", t.get().getPrice());
                    model.addAttribute("projectId", t.get().getProjectId());
                    model.addAttribute("ticketTypeId", t.get().getTicketTypeId());
                    model.addAttribute("typeName", t.get().getName());
                }
            }
        } catch (Exception e) {
            
        }
        return "buy";
    }

    @GetMapping("wechat/ticket/{id}")
    public String my(@PathVariable String id,HttpServletRequest request, Model model){
        
        try {
            Optional<Project> p =   dao.findById(id);

            if(p.isPresent()){

                model.addAttribute("projectId",id);
                model.addAttribute("banner",p.get().getBanner());

                if(request.getParameter("openId")==null){
                    String url=URLEncoder.encode(request.getScheme() + "://" + request.getServerName() + request.getRequestURI(),"utf-8");
                    return "redirect:" + request.getScheme() + "://" + request.getServerName() +"/wechat/welcome?projectId="+id+"&returnUrl="+url;
                }else{
                    
                    model.addAttribute("openId",request.getParameter("openId"));
                    return "myticket";
                }
            }
        } catch (Exception e) {
            
        }
        return "";
    }

    /**
     * 微信支付
     * @return
     */
    @GetMapping("wechat/index/{id}")
    public  ModelAndView  index(@PathVariable Long id,HttpServletRequest request, HttpServletResponse response) {
        
        ModelAndView map = new ModelAndView();

        try {
            Optional<OrderForm> form=formDao.findById(id);

            if(form.isPresent()){
                if(form.get().getIsPay()==0){
                    Optional<Project> project= dao.findById(form.get().getProjectId());

                    if(project.isPresent()){

                        PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
                        
                        prepayReqHandler.setParameter("appid", project.get().getAppId());
                        prepayReqHandler.setParameter("body", project.get().getName());
                        prepayReqHandler.setParameter("mch_id", project.get().getMerchantId());
                        String nonce_str = TenpayUtil.getNonceStr();
                        prepayReqHandler.setParameter("nonce_str", nonce_str);
                        prepayReqHandler.setParameter("notify_url", request.getScheme() + "://" + request.getServerName() +"/api/pay/notify/");
                        String out_trade_no = String.valueOf(System.currentTimeMillis());
                        prepayReqHandler.setParameter("out_trade_no", out_trade_no);
                        prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr());
                        prepayReqHandler.setParameter("openid", form.get().getOpenId());
                        prepayReqHandler.setParameter("total_fee", String.valueOf(form.get().getAmount()*100));
                        prepayReqHandler.setParameter("trade_type", "JSAPI");
                        prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign(project.get().getPaySecret()));
                        prepayReqHandler.setGateUrl(ConstantUtil.GATEURL);
                        String prepayid = prepayReqHandler.sendPrepay();
                        // 若获取prepayid成功，将相关信息返回客户端
                        if (prepayid != null && !prepayid.equals("")) {

                            String timestamp = TenpayUtil.getTimeStamp();
                            String signs = "appId=" + project.get().getAppId() + "&nonceStr=" + nonce_str + "&package=prepay_id="  + prepayid + "&signType=MD5&timeStamp=" + timestamp+"&key="+project.get().getPaySecret();
                            signs=TenpayUtil.MD5(signs);
                            map.addObject("sign", signs);
                            map.addObject("appid", project.get().getAppId());
                            map.addObject("timestamp", timestamp);  
                            map.addObject("noncestr", nonce_str);   
                            map.addObject("package", "prepay_id="+prepayid); 
                            map.addObject("openid", form.get().getOpenId());
                            map.addObject("projectid", form.get().getProjectId());
                            map.setViewName("index");
                            form.get().setWechatPayGuid(String.valueOf(out_trade_no));
                            formDao.save(form.get());
                        }else{
                            map.setStatus(HttpStatus.NOT_FOUND);
                        }
                    }else{
                        map.setStatus(HttpStatus.NOT_FOUND);
                    }
                }else{
                    map.setStatus(HttpStatus.NOT_FOUND);
                }
            }
        } catch (Exception e) {
            map.setStatus(HttpStatus.NOT_FOUND);
        }

        return map;
    }

    /**
     * 微信授权登录
     * @return
     */
    @GetMapping("wechat/welcome")
    @ApiOperation(value = "提示用户点击同意，授权登录")
    public String  welcome(@RequestParam("returnUrl") String returnUrl,
                           @RequestParam("projectId") String projectId,
                        HttpServletRequest request,
                        HttpServletResponse response) {
        WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();

        Optional<Project> project= dao.findById(projectId);
        if(project.isPresent()){
            wxMpConfigStorage.setAppId(project.get().getAppId());
            wxMpConfigStorage.setSecret(project.get().getAppSecret());
        }else{
            wxMpConfigStorage.setAppId(appId);
            wxMpConfigStorage.setSecret(appSecret);
        }

        WxMpServiceImpl  wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage);
        try {
            String url=URLEncoder.encode(returnUrl,"utf-8");
            String login_url= request.getScheme() + "://" + request.getServerName() + request.getContextPath()+"/wechat/login?returnUrl="+url+"&projectId="+projectId;        
            String oauth2buildAuthorizationUrl = wxMpService.oauth2buildAuthorizationUrl(login_url, WxConsts.OAuth2Scope.SNSAPI_BASE,  null);
    
            return "redirect:" + oauth2buildAuthorizationUrl;
        } catch (Exception e) {
            return "redirect:";
        }
    }

    /**
     * 通过code拿到数据openid
     * @param code
     * @param returnUrl
     * @return 进行网站跳转
     */
    @GetMapping("wechat/login")
    @ApiOperation(value = "通过code拿到数据openid")
    public String login(@RequestParam("code") String code,
                        @RequestParam("state") String state,
                        @RequestParam("returnUrl") String returnUrl,
                        @RequestParam("projectId") String projectId,
                        HttpServletRequest request,
                        HttpServletResponse response)throws ServletException, IOException  {

        try {
            WxMpOAuth2AccessToken wxMpOAuth2AccessToken = null;

            Optional<Project> project=dao.findById(projectId);
            if(project.isPresent()){
                WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
                wxMpConfigStorage.setAppId(project.get().getAppId());
                wxMpConfigStorage.setSecret(project.get().getAppSecret());
                WxMpServiceImpl  wxMpService = new WxMpServiceImpl();
                wxMpService.setWxMpConfigStorage(wxMpConfigStorage);
                wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
                
                String openId = wxMpOAuth2AccessToken.getOpenId();

                return "redirect:" + (returnUrl.indexOf("?")>0?returnUrl+"&openId="+openId:returnUrl+"?openId="+openId);
            }
        }catch(Exception e){

        }
            return "404";
        }
}
